Implement input shapes
authorAlexander Larsson <alexl@redhat.com>
Wed, 17 Dec 2008 10:24:46 +0000 (11:24 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:15:16 +0000 (10:15 +0200)
gdk/gdk.symbols
gdk/gdkinternals.h
gdk/gdkoffscreenwindow.c
gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/x11/gdkwindow-x11.c

index b0d82eba452218a7869f708342d9f9154566b166..0bd950030ed767caf547788f1fc2a42c9f7910d0 100644 (file)
@@ -666,6 +666,10 @@ gdk_window_shape_combine_mask
 gdk_window_shape_combine_region
 gdk_window_set_child_shapes
 gdk_window_merge_child_shapes
+gdk_window_input_shape_combine_mask
+gdk_window_input_shape_combine_region
+gdk_window_set_child_input_shapes
+gdk_window_merge_child_input_shapes
 gdk_window_set_static_gravities
 gdk_window_reparent
 gdk_window_add_filter
@@ -749,8 +753,6 @@ gdk_window_set_startup_id
 gdk_window_set_transient_for
 gdk_window_get_root_origin
 gdk_window_get_frame_extents
-gdk_window_input_shape_combine_mask
-gdk_window_input_shape_combine_region
 gdk_window_set_override_redirect
 gdk_window_set_accept_focus
 gdk_window_set_focus_on_map
@@ -774,8 +776,6 @@ gdk_window_set_group
 gdk_window_get_decorations
 gdk_window_set_decorations
 gdk_window_set_functions
-gdk_window_set_child_input_shapes
-gdk_window_merge_child_input_shapes
 gdk_window_begin_move_drag
 gdk_window_begin_resize_drag
 gdk_window_enable_synchronized_configure
index 7c119a493f46f3e196401e4b56893737ae898c2f..62d9f132fe362efeff4c453b77f4ca46ed9c22ce 100644 (file)
@@ -336,6 +336,7 @@ void     _gdk_windowing_window_get_offsets      (GdkWindow  *window,
                                                 gint       *x_offset,
                                                 gint       *y_offset);
 GdkRegion *_gdk_windowing_window_get_shape      (GdkWindow  *window);
+GdkRegion *_gdk_windowing_window_get_input_shape(GdkWindow  *window);
 GdkRegion *_gdk_windowing_get_shape_for_mask    (GdkBitmap *mask);
 
 
index 1fa7018e78fbc367a57c8d174f0d18ba8386c5de..408a27dc570b16782e62bfdebfebc3d5ae8059a7 100644 (file)
@@ -1010,12 +1010,10 @@ gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
 }
 
 static void
-gdk_offscreen_window_set_child_shapes (GdkWindow *window)
-{
-}
-
-static void
-gdk_offscreen_window_merge_child_shapes (GdkWindow *window)
+gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
+                                                const GdkRegion *shape_region,
+                                                gint             offset_x,
+                                                gint             offset_y)
 {
 }
 
@@ -1170,8 +1168,7 @@ gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->set_cursor = gdk_offscreen_window_set_cursor;
   iface->get_geometry = gdk_offscreen_window_get_geometry;
   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
-  iface->set_child_shapes = gdk_offscreen_window_set_child_shapes;
-  iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes;
+  iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
   iface->queue_translation = gdk_offscreen_window_queue_translation;
index 6ea81d042d914b15733991af027a003dfbe43ebc..8fdb622ec3a2523ac6aef64b9c4d91646098584c 100644 (file)
@@ -383,6 +383,12 @@ gdk_window_finalize (GObject *object)
       obj->impl = NULL;
     }
 
+  if (obj->shape)
+    gdk_region_destroy (obj->shape);
+
+  if (obj->input_shape)
+    gdk_region_destroy (obj->input_shape);
+
   if (obj->cursor)
     gdk_cursor_unref (obj->cursor);
 
@@ -431,12 +437,14 @@ gdk_window_has_no_impl (GdkWindowObject *window)
 static void
 remove_child_area (GdkWindowObject *private,
                   GdkWindowObject *until,
+                  gboolean for_input,
                   GdkRegion *region)
 {
   GdkWindowObject *child;
   GdkRegion *child_region;
   GdkRectangle r;
   GList *l;
+  GdkRegion *shape;
   
   for (l = private->children; l; l = l->next)
     {
@@ -464,7 +472,6 @@ remove_child_area (GdkWindowObject *private,
        gdk_region_intersect (child_region, child->shape);
       else if (private->window_type == GDK_WINDOW_FOREIGN)
        {
-         GdkRegion *shape;
          shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
          if (shape)
            {
@@ -472,6 +479,21 @@ remove_child_area (GdkWindowObject *private,
              gdk_region_destroy (shape);
            }
        }
+
+      if (for_input)
+       {
+         if (child->input_shape)
+           gdk_region_intersect (child_region, child->input_shape);
+         else if (private->window_type == GDK_WINDOW_FOREIGN)
+           {
+             shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
+             if (shape)
+               {
+                 gdk_region_intersect (child_region, shape);
+                 gdk_region_destroy (shape);
+               }
+           }
+       }
       
       gdk_region_subtract (region, child_region);
       gdk_region_destroy (child_region);
@@ -533,7 +555,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
          gdk_region_intersect (new_clip, private->parent->clip_region);
          
          /* Remove all overlapping children from parent */
-         remove_child_area (private->parent, private, new_clip);
+         remove_child_area (private->parent, private, FALSE, new_clip);
        }
       
       /* Convert from parent coords to window coords */
@@ -552,7 +574,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
 
       old_clip_region_with_children = private->clip_region_with_children;
       private->clip_region_with_children = gdk_region_copy (private->clip_region);
-      remove_child_area (private, NULL, private->clip_region_with_children);
+      remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
 
       if (clip_region_changed ||
          !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
@@ -590,8 +612,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
     {
       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
     }
-      
-  
+
   if (recalculate_siblings &&
       private->parent != NULL &&
       GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
@@ -1119,6 +1140,8 @@ gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
       
       private->impl = old_impl;
       change_impl (private, new_impl);
+
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
     }
   else
     {
@@ -6275,7 +6298,7 @@ do_child_shapes (GdkWindow *window,
   r.height = private->height;
   
   region = gdk_region_rectangle (&r);
-  remove_child_area (private, NULL, region);
+  remove_child_area (private, NULL, FALSE, region);
 
   if (merge && private->shape)
     gdk_region_subtract (region, private->shape);
@@ -6321,6 +6344,182 @@ gdk_window_merge_child_shapes (GdkWindow *window)
   do_child_shapes (window, TRUE);
 }
 
+/**
+ * gdk_window_input_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ * 
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+                                    GdkBitmap *mask,
+                                    gint       x,
+                                    gint       y)
+{
+  GdkWindowObject *private;
+  GdkRegion *region;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+
+  region = _gdk_windowing_get_shape_for_mask (mask);
+
+  gdk_window_input_shape_combine_region (window,
+                                        region,
+                                        x, y);
+  
+  gdk_region_destroy (region);
+}
+
+/**
+ * gdk_window_input_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ * 
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_region (GdkWindow       *window,
+                                      const GdkRegion *shape_region,
+                                      gint             offset_x,
+                                      gint             offset_y)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (private->input_shape)
+    gdk_region_destroy (private->input_shape);
+
+  if (shape_region)
+    {
+      private->input_shape = gdk_region_copy (shape_region);
+      gdk_region_offset (private->shape, offset_x, offset_y);      
+    }
+  else
+    private->input_shape = NULL;
+
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
+
+  /* Pointer may have e.g. moved outside window due to the input mask change */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+do_child_input_shapes (GdkWindow *window,
+                      gboolean merge)
+{
+  GdkWindowObject *private;
+  GdkRectangle r;
+  GdkRegion *region;
+
+  private = (GdkWindowObject *) window;
+  
+  r.x = 0;
+  r.y = 0;
+  r.width = private->width;
+  r.height = private->height;
+  
+  region = gdk_region_rectangle (&r);
+  remove_child_area (private, NULL, TRUE, region);
+
+  if (merge && private->shape)
+    gdk_region_subtract (region, private->shape);
+  if (merge && private->input_shape)
+    gdk_region_subtract (region, private->input_shape);
+  
+  gdk_window_input_shape_combine_region (window, region, 0, 0);
+}
+
+
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_set_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  do_child_input_shapes (window, FALSE);
+}
+
+/**
+ * gdk_window_merge_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of 
+ * shapes to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_merge_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  do_child_input_shapes (window, TRUE);
+}
+
 
 /**
  * gdk_window_set_static_gravities:
@@ -6713,6 +6912,9 @@ point_in_window (GdkWindowObject *window,
     y >= 0 && y < window->height &&
     (window->shape == NULL ||
      gdk_region_point_in (window->shape,
+                         x, y)) &&
+    (window->input_shape == NULL ||
+     gdk_region_point_in (window->input_shape,
                          x, y));
 }
 
index bc08cbc51ba15b5f48599f3a3700b5caaac99766..0956dd693e8bf2490858e8d4c180dc72b3a91dd0 100644 (file)
@@ -339,6 +339,7 @@ struct _GdkWindowObject
   GList *outstanding_moves;
 
   GdkRegion *shape;
+  GdkRegion *input_shape;
   
   cairo_surface_t *cairo_surface;
 };
index 5b252a2abf4a6ec3949ceb4c1d7335fa36ec5dab..dacaf747a7972513bbd44ecfcba71cc80f669f6b 100644 (file)
@@ -90,8 +90,10 @@ struct _GdkWindowImplIface
                                          const GdkRegion *shape_region,
                                          gint             offset_x,
                                          gint             offset_y);
-  void         (* set_child_shapes)     (GdkWindow       *window);
-  void         (* merge_child_shapes)   (GdkWindow       *window);
+  void         (* input_shape_combine_region) (GdkWindow       *window,
+                                              const GdkRegion *shape_region,
+                                              gint             offset_x,
+                                              gint             offset_y);
 
   gboolean     (* set_static_gravities) (GdkWindow       *window,
                                         gboolean         use_static);
index 90f38964cba086c41db7421fecb2f2b8ae55b575..f2641f7d1f9b6b9a1ba03856f690685145afe253 100644 (file)
@@ -3375,44 +3375,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-/**
- * gdk_window_input_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- * 
- * Like gdk_window_shape_combine_mask(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the 
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are 
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void 
-gdk_window_input_shape_combine_mask (GdkWindow *window,
-                                    GdkBitmap *mask,
-                                    gint       x,
-                                    gint       y)
-{
-#ifdef ShapeInput
-  do_shape_combine_mask (window, mask, x, y, ShapeInput);
-#endif
-}
-
-
 static inline void
 do_shape_combine_region (GdkWindow       *window,
                         const GdkRegion *shape_region,
@@ -3479,37 +3441,11 @@ gdk_window_x11_shape_combine_region (GdkWindow       *window,
   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
 }
 
-/**
- * gdk_window_input_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- * 
- * Like gdk_window_shape_combine_region(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the 
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are 
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void 
-gdk_window_input_shape_combine_region (GdkWindow       *window,
-                                      const GdkRegion *shape_region,
-                                      gint             offset_x,
-                                      gint             offset_y)
+static void 
+gdk_window_x11_input_shape_combine_region (GdkWindow       *window,
+                                          const GdkRegion *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
 {
 #ifdef ShapeInput
   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
@@ -4568,152 +4504,10 @@ gdk_window_set_functions (GdkWindow    *window,
   gdk_window_set_mwm_hints (window, &hints);
 }
 
-#ifdef HAVE_SHAPE_EXT
-
-/* 
- * propagate the shapes from all child windows of a GDK window to the parent 
- * window. Shamelessly ripped from Enlightenment's code
- * 
- * - Raster
- */
-struct _gdk_span
-{
-  gint                start;
-  gint                end;
-  struct _gdk_span    *next;
-};
-
-static void
-gdk_add_to_span (struct _gdk_span **s,
-                gint               x,
-                gint               xx)
-{
-  struct _gdk_span *ptr1, *ptr2, *noo, *ss;
-  gchar             spanning;
-  
-  ptr2 = NULL;
-  ptr1 = *s;
-  spanning = 0;
-  ss = NULL;
-  /* scan the spans for this line */
-  while (ptr1)
-    {
-      /* -- -> new span */
-      /* == -> existing span */
-      /* ## -> spans intersect */
-      /* if we are in the middle of spanning the span into the line */
-      if (spanning)
-       {
-         /* case: ---- ==== */
-         if (xx < ptr1->start - 1)
-           {
-             /* ends before next span - extend to here */
-             ss->end = xx;
-             return;
-           }
-         /* case: ----##=== */
-         else if (xx <= ptr1->end)
-           {
-             /* crosses into next span - delete next span and append */
-             ss->end = ptr1->end;
-             ss->next = ptr1->next;
-             g_free (ptr1);
-             return;
-           }
-         /* case: ---###--- */
-         else
-           {
-             /* overlaps next span - delete and keep checking */
-             ss->next = ptr1->next;
-             g_free (ptr1);
-             ptr1 = ss;
-           }
-       }
-      /* otherwise havent started spanning it in yet */
-      else
-       {
-         /* case: ---- ==== */
-         if (xx < ptr1->start - 1)
-           {
-             /* insert span here in list */
-             noo = g_malloc (sizeof (struct _gdk_span));
-             
-             if (noo)
-               {
-                 noo->start = x;
-                 noo->end = xx;
-                 noo->next = ptr1;
-                 if (ptr2)
-                   ptr2->next = noo;
-                 else
-                   *s = noo;
-               }
-             return;
-           }
-         /* case: ----##=== */
-         else if ((x < ptr1->start) && (xx <= ptr1->end))
-           {
-             /* expand this span to the left point of the new one */
-             ptr1->start = x;
-             return;
-           }
-         /* case: ===###=== */
-         else if ((x >= ptr1->start) && (xx <= ptr1->end))
-           {
-             /* throw the span away */
-             return;
-           }
-         /* case: ---###--- */
-         else if ((x < ptr1->start) && (xx > ptr1->end))
-           {
-             ss = ptr1;
-             spanning = 1;
-             ptr1->start = x;
-             ptr1->end = xx;
-           }
-         /* case: ===##---- */
-         else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
-           {
-             ss = ptr1;
-             spanning = 1;
-             ptr1->end = xx;
-           }
-         /* case: ==== ---- */
-         /* case handled by next loop iteration - first case */
-       }
-      ptr2 = ptr1;
-      ptr1 = ptr1->next;
-    }
-  /* it started in the middle but spans beyond your current list */
-  if (spanning)
-    {
-      ptr2->end = xx;
-      return;
-    }
-  /* it does not start inside a span or in the middle, so add it to the end */
-  noo = g_malloc (sizeof (struct _gdk_span));
-  
-  if (noo)
-    {
-      noo->start = x;
-      noo->end = xx;
-      if (ptr2)
-       {
-         noo->next = ptr2->next;
-         ptr2->next = noo;
-       }
-      else
-       {
-         noo->next = NULL;
-         *s = noo;
-       }
-    }
-  return;
-}
-
 static GdkRegion *
 xwindow_get_shape (Display *xdisplay,
-                  Window window)
+                  Window window,
+                  gint shape_type)
 {
   GdkRegion *shape;
   GdkRectangle *rl;
@@ -4725,8 +4519,8 @@ xwindow_get_shape (Display *xdisplay,
 #if defined(HAVE_SHAPE_EXT)
   xrl = XShapeGetRectangles (xdisplay,
                             window,
-                            ShapeBounding, &rn, &ord);
-
+                            shape_type, &rn, &ord);
+  
   if (rn == 0)
     return gdk_region_new (); /* Empty */
   
@@ -4778,7 +4572,7 @@ _gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
                     ShapeSet);
   
   region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
-                             window);
+                             window, ShapeBounding);
 
   XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
                  window);
@@ -4793,273 +4587,26 @@ _gdk_windowing_window_get_shape (GdkWindow *window)
   if (!GDK_WINDOW_DESTROYED (window) &&
       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
     return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
-                             GDK_WINDOW_XID (window));
+                             GDK_WINDOW_XID (window), ShapeBounding);
 #endif
 
   return NULL;
 }
 
-static void
-gdk_add_rectangles (Display           *disp,
-                   Window             win,
-                   struct _gdk_span **spans,
-                   gint               basew,
-                   gint               baseh,
-                   gint               x,
-                   gint               y)
-{
-  gint a, k;
-  gint x1, y1, x2, y2;
-  gint rn, ord;
-  XRectangle *rl;
-  
-  rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
-  if (rl)
-    {
-      /* go through all clip rects in this window's shape */
-      for (k = 0; k < rn; k++)
-       {
-         /* for each clip rect, add it to each line's spans */
-         x1 = x + rl[k].x;
-         x2 = x + rl[k].x + (rl[k].width - 1);
-         y1 = y + rl[k].y;
-         y2 = y + rl[k].y + (rl[k].height - 1);
-         if (x1 < 0)
-           x1 = 0;
-         if (y1 < 0)
-           y1 = 0;
-         if (x2 >= basew)
-           x2 = basew - 1;
-         if (y2 >= baseh)
-           y2 = baseh - 1;
-         for (a = y1; a <= y2; a++)
-           {
-             if ((x2 - x1) >= 0)
-               gdk_add_to_span (&spans[a], x1, x2);
-           }
-       }
-      XFree (rl);
-    }
-}
-
-static void
-gdk_propagate_shapes (Display *disp,
-                     Window   win,
-                     gboolean merge,
-                     int      shape)
-{
-  Window              rt, par, *list = NULL;
-  gint                i, j, num = 0, num_rects = 0;
-  gint                x, y, contig;
-  guint               w, h, d;
-  gint                baseh, basew;
-  XRectangle         *rects = NULL;
-  struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
-  XWindowAttributes   xatt;
-  
-  XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
-  if (h <= 0)
-    return;
-  basew = w;
-  baseh = h;
-  spans = g_malloc (sizeof (struct _gdk_span *) * h);
-  
-  for (i = 0; i < h; i++)
-    spans[i] = NULL;
-  XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
-  if (list)
-    {
-      /* go through all child windows and create/insert spans */
-      for (i = 0; i < num; i++)
-       {
-         if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
-           if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
-             gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
-       }
-      if (merge)
-       gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
-      
-      /* go through the spans list and build a list of rects */
-      rects = g_malloc (sizeof (XRectangle) * 256);
-      num_rects = 0;
-      for (i = 0; i < baseh; i++)
-       {
-         ptr1 = spans[i];
-         /* go through the line for all spans */
-         while (ptr1)
-           {
-             rects[num_rects].x = ptr1->start;
-             rects[num_rects].y = i;
-             rects[num_rects].width = ptr1->end - ptr1->start + 1;
-             rects[num_rects].height = 1;
-             j = i + 1;
-             /* if there are more lines */
-             contig = 1;
-             /* while contigous rects (same start/end coords) exist */
-             while ((contig) && (j < baseh))
-               {
-                 /* search next line for spans matching this one */
-                 contig = 0;
-                 ptr2 = spans[j];
-                 ptr3 = NULL;
-                 while (ptr2)
-                   {
-                     /* if we have an exact span match set contig */
-                     if ((ptr2->start == ptr1->start) &&
-                         (ptr2->end == ptr1->end))
-                       {
-                         contig = 1;
-                         /* remove the span - not needed */
-                         if (ptr3)
-                           {
-                             ptr3->next = ptr2->next;
-                             g_free (ptr2);
-                             ptr2 = NULL;
-                           }
-                         else
-                           {
-                             spans[j] = ptr2->next;
-                             g_free (ptr2);
-                             ptr2 = NULL;
-                           }
-                         break;
-                       }
-                     /* gone past the span point no point looking */
-                     else if (ptr2->start < ptr1->start)
-                       break;
-                     if (ptr2)
-                       {
-                         ptr3 = ptr2;
-                         ptr2 = ptr2->next;
-                       }
-                   }
-                 /* if a contiguous span was found increase the rect h */
-                 if (contig)
-                   {
-                     rects[num_rects].height++;
-                     j++;
-                   }
-               }
-             /* up the rect count */
-             num_rects++;
-             /* every 256 new rects increase the rect array */
-             if ((num_rects % 256) == 0)
-               rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
-             ptr1 = ptr1->next;
-           }
-       }
-      /* set the rects as the shape mask */
-      if (rects)
-       {
-         XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
-                                  ShapeSet, YXSorted);
-         g_free (rects);
-       }
-      XFree (list);
-    }
-  /* free up all the spans we made */
-  for (i = 0; i < baseh; i++)
-    {
-      ptr1 = spans[i];
-      while (ptr1)
-       {
-         ptr2 = ptr1;
-         ptr1 = ptr1->next;
-         g_free (ptr2);
-       }
-    }
-  g_free (spans);
-}
-
-#endif /* HAVE_SHAPE_EXT */
-
-static inline void
-do_child_shapes (GdkWindow *window,
-                 gboolean   merge)
-{
-#ifdef HAVE_SHAPE_EXT
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                            GDK_WINDOW_XID (window),
-                            merge,
-                            ShapeBounding);
-    }
-#endif
-}
-
-static void
-gdk_window_x11_set_child_shapes (GdkWindow *window)
-{
-  do_child_shapes (window, FALSE);
-}
-
-static void
-gdk_window_x11_merge_child_shapes (GdkWindow *window)
-{
-  do_child_shapes (window, TRUE);
-}
-
-static inline void
-do_child_input_shapes (GdkWindow *window,
-                       gboolean   merge)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
 {
-#if defined(HAVE_SHAPE_EXT) && defined(ShapeInput)
+#if defined(HAVE_SHAPE_EXT)
   if (!GDK_WINDOW_DESTROYED (window) &&
       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                            GDK_WINDOW_XID (window),
-                            merge,
-                            ShapeInput);
-    }
+    return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                             GDK_WINDOW_XID (window),
+                             ShapeInput);
 #endif
-}
-
-/**
- * gdk_window_set_child_input_shapes:
- * @window: a #GdkWindow
- * 
- * Sets the input shape mask of @window to the union of input shape masks
- * for all children of @window, ignoring the input shape mask of @window
- * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
- * the input shape mask of @window in the masks to be merged.
- *
- * Since: 2.10
- **/
-void 
-gdk_window_set_child_input_shapes (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  do_child_input_shapes (window, FALSE);
-}
 
-/**
- * gdk_window_merge_child_input_shapes:
- * @window: a #GdkWindow
- * 
- * Merges the input shape masks for any child windows into the
- * input shape mask for @window. i.e. the union of all input masks
- * for @window and its children will become the new input mask
- * for @window. See gdk_window_input_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_input_shapes()
- * because it includes @window's input shape mask in the set of 
- * shapes to be merged.
- *
- * Since: 2.10
- **/
-void 
-gdk_window_merge_child_input_shapes (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  do_child_input_shapes (window, TRUE);
+  return NULL;
 }
 
-
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window,
                                    gboolean   on)
@@ -5962,8 +5509,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->get_origin = gdk_window_x11_get_origin;
   iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin;
   iface->shape_combine_region = gdk_window_x11_shape_combine_region;
-  iface->set_child_shapes = gdk_window_x11_set_child_shapes;
-  iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
+  iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
   iface->set_static_gravities = gdk_window_x11_set_static_gravities;
   iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
   iface->queue_translation = _gdk_x11_window_queue_translation;